#!/usr/bin/env bash
. wvtest.sh
. wvtest-bup.sh
. dev/lib.sh

set -o pipefail

top="$(WVPASS pwd)" || exit $?
tmpdir="$(WVPASS wvmktempdir)" || exit $?
export BUP_DIR="$tmpdir/bup"

bup() { "$top/bup" "$@"; }

WVPASS cd "$tmpdir"

# necessary for 0 == 1970-01-01 00:00
export TZ=UTC

WVSTART "init"
WVPASS bup init

mkdir "$tmpdir/save"
for f in $(seq 9) ; do
    touch -t 200${f}01010000 "$tmpdir/save/$f"
done
mkdir "$tmpdir/save/a"
touch -t 199901010000 "$tmpdir/save/a/1"

WVSTART "metadata read error for a file"
WVPASS bup index "$tmpdir/save"

# Inject save errors while reading metadata via --import-py-module.
WVPASS rm -rf "$tmpdir/mod"
WVPASS mkdir -p "$tmpdir/mod"
cat > "$tmpdir/mod/bup_fail_on_5.py" << EOF
from bup import metadata

orig_from_path = metadata.from_path
def from_path(path, *args, **kw):
    if path.endswith(b'/5'):
        raise IOError('intentionally failing metadata read for .../5')
    return orig_from_path(path, *args, **kw)
metadata.from_path = from_path
EOF

PYTHONPATH="$tmpdir/mod" \
          bup --import-py-module bup_fail_on_5 save -n test "$tmpdir/save"

# this should work anyway
WVPASS bup ls -l "test/latest/$tmpdir/save"
# also check the *right* data was returned
lsout="$(bup ls -l "test/latest/$tmpdir/save")"
for f in 1 2 3 4   6 7 8 9 ; do
    if ! echo "$lsout" | grep "200${f}-01-01 00:00 $f" ; then
        WVFAIL echo incorrect date for $f
    fi
done
# and ensure we actually failed, and the above script/hack didn't break
if echo "$lsout" | grep " 5$" ; then
    WVFAIL echo unexpectedly stored data for file 5
fi


WVSTART "metadata read error for a folder"
WVPASS bup index --clear
WVPASS bup index "$tmpdir/save"

# Inject save errors while reading metadata via --import-py-module.
WVPASS rm -rf "$tmpdir/mod"
WVPASS mkdir -p "$tmpdir/mod"
cat > "$tmpdir/mod/bup_fail_on_a.py" << EOF
from bup import metadata

orig_from_path = metadata.from_path
def from_path(path, *args, **kw):
    if path.endswith(b'/a'):
        raise IOError('intentionally failing metadata read for .../a')
    return orig_from_path(path, *args, **kw)
metadata.from_path = from_path
EOF

PYTHONPATH="$tmpdir/mod" \
          bup --import-py-module bup_fail_on_a save -n test "$tmpdir/save"

# this should work anyway
WVPASS bup ls -l "test/latest/$tmpdir/save"
if ! bup ls -l "test/latest/$tmpdir/save/a" | grep '1999-01-01 00:00 1' ; then
    WVFAIL unexpected date for file a/1
fi
# and ensure we actually failed, and the above script/hack didn't break
if ! bup ls -l "test/latest/$tmpdir/save" | grep "????-??-?? ??:?? a" ; then
    WVFAIL unexpected date for directory a
fi


WVSTART "duplicate entries"
WVPASS bup index --clear
WVPASS bup index "$tmpdir/save"

# Inject save errors while reading metadata via --import-py-module.
WVPASS rm -rf "$tmpdir/mod"
WVPASS mkdir -p "$tmpdir/mod"
cat > "$tmpdir/mod/bup_dup_reader_path.py" << EOF
from bup import index

Reader = index.Reader
class DupReader(index.Reader):
    def filter(self, *args, **kw):
        for transname, ent in Reader.filter(self, *args, **kw):
            # duplicate a file and a folder
            if ent.name.endswith(b'/5') or ent.name.endswith(b'/a/'):
                yield transname, ent
            yield transname, ent
index.Reader = DupReader
EOF

PYTHONPATH="$tmpdir/mod" \
          bup --import-py-module bup_dup_reader_path save -n test "$tmpdir/save"

# this should work
WVPASS bup ls -l "test/latest/$tmpdir/save"

# check that there are no duplicates
lsout=$(bup ls -l "test/latest/$tmpdir/save")
WVPASSEQ "$(echo "$lsout" | sort | uniq -d)" ""

# and we should get the *right* data for each entry
for f in $(seq 9) ; do
    if ! echo "$lsout" | grep "200${f}-01-01 00:00 $f" ; then
        WVFAIL echo incorrect metadata for $f
    fi
done


WVPASS cd "$top"
WVPASS rm -rf "$tmpdir"
